﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Telerik.Charting;
using PClusterModel;
using PClusterModel.Cluster;
using PClusterModel.Utils;
using PClusterModel.Infrastructure;

namespace MicroarrayDataPresentation
{
    public partial class FormClusterization : Form
    {
        private Report report;
        private ReportForm reportForm;
        BackgroundWorker worker;

        public FormClusterization()
        {
            InitializeComponent();
            radioButtonClustered.CheckedChanged += new EventHandler(radioButtonClustered_CheckedChanged);
            worker = new BackgroundWorker();
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        }

        private void btnClusterize_Click(object sender, EventArgs e)
        {
            worker.RunWorkerAsync();
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            IList<IMicroarrayCluster> allClusters = e.Result as IList<IMicroarrayCluster>;
            if (allClusters != null)
            {
                this.BindClustersComboBox(allClusters);
                if (this.reportForm == null)
                {
                    this.reportForm = new ReportForm(this.report);
                }
                else
                {
                    this.reportForm.Report = this.report;
                }
                this.reportForm.ShowDialog();
            }
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            IList<IMicroarrayCluster> allClusters = PerformClustering();
            e.Result = allClusters;
        }

        private IList<IMicroarrayCluster> PerformClustering()
        {
            string dataFile = this.GetDataFilePath();
            MicroarrayDataMatrix matrix = DataLoader.LoadData(dataFile);

            byte delta = (byte)this.numTrashold.Value;
            int nr = (int)this.numRows.Value;
            int nc = (int)this.numColumns.Value;
            PatternType pattern = radioButtonShifting.Checked ? PatternType.Shifting : PatternType.Scaling;

            PClusterizer clusterizer = new PClusterizer(matrix, delta, nr, nc, pattern);
            this.report = new Report(clusterizer);

            IList<IMicroarrayCluster> allClusters = clusterizer.Clusterize();

            return allClusters;
        }

        private string GetDataFilePath()
        {
            string dataFilePath = null;
            if (this.radioButtonDemoData.Checked)
            {
                dataFilePath = @"..\..\Data\YeastMicroarrayData-DEMO.txt";
            }
            else if (this.radioButtonYeastFull.Checked)
            {
                dataFilePath = @"..\..\Data\YeastMicroarrayData-FULL.txt";
            }
            else if (this.radioButtonUserSpecified.Checked)
            {
                dataFilePath = radioButtonUserSpecified.Tag as string;
            }

            if (string.IsNullOrEmpty(dataFilePath))
            {
                throw new InvalidOperationException("No data available for performing clusterization");
            }
            return dataFilePath;
        }

        private void BindClustersComboBox(IList<IMicroarrayCluster> allClusters)
        {
            if (allClusters == null || allClusters.Count == 0)
            {
                this.comboBoxClusters.DataSource = null;
                this.comboBoxClusters.Items.Add("No Clusters Availabale With Current Input Parameters");
                this.comboBoxClusters.SelectedIndex = 0;
                return;
            }

            List<ClusterUIWrapper> clusterItems = new List<ClusterUIWrapper>();
            for (int i = 0; i < allClusters.Count; i++)
            {
                IMicroarrayCluster cluster = allClusters[i];
                ClusterUIWrapper item = new ClusterUIWrapper();
                item.Cluster = cluster;
                item.DisplayName = string.Format("{0}x{1} Cluster No:{2}", cluster.NumberOfObjects, cluster.NumberOfConditions, i + 1);
                clusterItems.Add(item);
            }
            this.comboBoxClusters.DataSource = clusterItems;
            this.comboBoxClusters.DisplayMember = "DisplayName";
        }

        private void BindChart(ClusterUIWrapper selectedCluster, bool clustered)
        {
            ChartSeries[] series = this.TransformClusterDataToChartData(selectedCluster, clustered);
            this.radChartClusters.Series.Clear();
            this.radChartClusters.Series.AddRange(series);
            this.radChartClusters.DataBind();
        }

        private ChartSeries[] TransformClusterDataToChartData(ClusterUIWrapper clusterWrapper, bool clustered)
        {
            IMicroarrayCluster cluster = clusterWrapper.Cluster;
            List<ChartSeries> series = new List<ChartSeries>();
            foreach (Gene gene in cluster.ObjectsInCluster)
            {
                ChartSeries chartSeries = new ChartSeries(gene.Name);
                chartSeries.Type = ChartSeriesType.Line;
                for (int condition = 0; condition < cluster.ClusteringConditions.Count; condition++)
                {
                    if (cluster.ClusteringConditions[condition] || clustered == false)
                    {
                        ChartSeriesItem item = new ChartSeriesItem(condition + 1, gene.ExpresionValues[condition]);
                        chartSeries.Items.Add(item);
                    }
                }
                series.Add(chartSeries);
            }
            return series.ToArray();
        }

        private void comboBoxClusters_SelectedIndexChanged(object sender, EventArgs e)
        {
            ClusterUIWrapper selectedCluster = this.comboBoxClusters.SelectedItem as ClusterUIWrapper;
            if (selectedCluster != null)
            {
                BindChart(selectedCluster, this.radioButtonClustered.Checked);
            }
        }

        private void radioButtonClustered_CheckedChanged(object sender, EventArgs e)
        {
            ClusterUIWrapper selectedItem = comboBoxClusters.SelectedItem as ClusterUIWrapper;
            if (selectedItem != null)
            {
                BindChart(selectedItem, this.radioButtonClustered.Checked);
            }
        }

        private void btnUserData_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.radioButtonUserSpecified.Tag = dialog.FileName;
            }
        }
    }

    public class ClusterUIWrapper
    {
        public string DisplayName
        { get; set; }

        public IMicroarrayCluster Cluster
        { get; set; }
    }
}
